home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / Finger Server Source / sip_glue.cp < prev    next >
Text File  |  1993-08-13  |  10KB  |  413 lines

  1. /*
  2.  * tcp io routines to for finger server
  3.  * by Aaron Wohl n3liw+@cmu.edu
  4.  * 412-268-5032 / 412-731-3691
  5.  */
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "sip_glue.h"
  10. #include "sip_interface.h"
  11.  
  12. static struct {
  13.     tcp_conv_pt  all_tcp_convs;
  14.     int refnum;
  15.     process_wakeup_control server_proc;
  16. } ip_gl;
  17.  
  18. /*
  19.  * wake the passed process
  20.  */
  21. static void tcp_wake(process_wakeup_control_pt wake_me)
  22. {
  23.     if(wake_me->tcp_wake_magic_num!=TCP_WAKE_MAGIC_NUM)
  24.         Debugger();
  25.     wake_me->can_sleep=FALSE;
  26.     if(!wake_me->need_wake_up)
  27.         return;
  28.     // wake waiting process so it can handle the event
  29.     if(WakeUpProcess(&wake_me->server))
  30.         wake_me->need_wake_up=FALSE;
  31. }
  32.  
  33. /*
  34.  * io compleation proc to awake the server process if needed
  35.  */
  36. static pascal void tcp_io_compleation_proc(void)
  37. {
  38.     asm {
  39.         movem.l    a0-a2/a5/d0-d2,-(sp)
  40.         move.l    tcp_side.sconv(a0),a0
  41.         move.l    tcp_conv.server_proc(a0),a0
  42.         move.l    process_wakeup_control.a5(a0),a5
  43.         move.l     a0,-(sp)
  44.         bsr        tcp_wake
  45.         move.l    (sp)+,a0            //remove the argument
  46.         movem.l    (sp)+,a0-a2/a5/d0-d2
  47.     }
  48. }
  49.  
  50. /*
  51.  * Do a tcp io operation on a connection
  52.  */
  53. static int tcp_do_tio_any(tcp_conv_pt sconv,TCPiopb *ipb,int is_async)
  54. {
  55.     int iErr;
  56.     ipb->ioCRefNum = ip_gl.refnum;
  57.     ipb->tcpStream = sconv->tcpStream;
  58.     iErr=PBControl((ParmBlkPtr)ipb,is_async);
  59.     if(iErr>=0)
  60.         return FALSE;
  61.     tcp_release_connection(sconv);
  62.     return TRUE;
  63. }
  64.  
  65. /*
  66.  * Do a tcp io operation on a connection
  67.  */
  68. static int tcp_do_tio(tcp_conv_pt sconv,TCPiopb *ipb)
  69. {
  70.     return tcp_do_tio_any(sconv,ipb,FALSE);
  71. }
  72.  
  73. /*
  74.  * Do a tcp io operation on a connection
  75.  */
  76. static int tcp_do_tio_async(tcp_conv_pt sconv,side_pt aside)
  77. {
  78.     aside->sconv=sconv;
  79.     aside->ipb.ioCompletion= (void*)&tcp_io_compleation_proc;
  80.     return tcp_do_tio_any(sconv,&aside->ipb,TRUE);
  81. }
  82.  
  83. /*
  84.  * passive connection to listen for incomming tcp connections
  85.  */
  86. int tcp_passive_connect(tcp_conv_pt sconv,tcp_port port_number)
  87. {
  88.     memset(&sconv->write_side.ipb,0,sizeof(sconv->write_side.ipb));
  89.     sconv->write_side.ipb.csParam.open.localPort = port_number;
  90.        sconv->write_side.ipb.csParam.open.userDataPtr = (char*)sconv;
  91.        sconv->write_side.ipb.csCode = TCPPassiveOpen;
  92.     if(tcp_do_tio_async(sconv,&sconv->write_side))
  93.         return TRUE;
  94.     sconv->state=ST_LISTEN;
  95.     return FALSE;
  96. }
  97.  
  98. #include <stdio.h>
  99.  
  100. /*
  101.  * setup one stream
  102.  */
  103. int tcp_init_stream(tcp_conv_pt sconv)
  104. {
  105.     memset(sconv,0,sizeof(*sconv));
  106.     if(tcp_create_stream(sconv))
  107.         return TRUE;
  108.     if(sconv->tcpStream==0)
  109.         return TRUE;
  110.     return tcp_passive_connect(sconv,TCP_FINGER_PORT);
  111. }
  112.  
  113. /*
  114.  * just woke up and will service any requests
  115.  */
  116. void tcp_just_awoke(void)
  117. {
  118.     ip_gl.server_proc.need_wake_up=FALSE;
  119.     ip_gl.server_proc.can_sleep=TRUE;
  120. }
  121.  
  122. /*
  123.  * did any new events happens since we last awoke?
  124.  */
  125. int tcp_ok_to_sleep_now(void)
  126. {
  127.     ip_gl.server_proc.need_wake_up=TRUE;        //in case interupt hits after can_sleep check
  128.     return ip_gl.server_proc.can_sleep;
  129. }
  130.  
  131. /*
  132.  * init system to wake us up when async io finishes
  133.  */
  134. static int tcp_init_wakeup(void)
  135. {
  136.     // get serial num so it can wake us later
  137.     if(GetCurrentProcess(&ip_gl.server_proc.server))
  138.         return TRUE;
  139.     ip_gl.server_proc.need_wake_up=FALSE;
  140.     ip_gl.server_proc.can_sleep=FALSE;
  141.     ip_gl.server_proc.a5=CurrentA5;
  142.     ip_gl.server_proc.tcp_wake_magic_num=TCP_WAKE_MAGIC_NUM;
  143.     return FALSE;
  144. }
  145.  
  146. /*
  147.  * setup all the streams
  148.  */
  149. int tcp_init_streams(void)
  150. {
  151.      int i;
  152.      if(tcp_init_wakeup())
  153.          return TRUE;
  154.      for(i=0;i<MAX_NUM_CONVS;i++)
  155.          tcp_init_stream(ip_gl.all_tcp_convs+i);
  156.      return FALSE;
  157. }
  158.  
  159. /*
  160.  * clean up all the streams
  161.  */
  162. void tcp_release_streams(void)
  163. {
  164.      int i;
  165.      for(i=0;i<MAX_NUM_CONVS;i++) {
  166.          tcp_conv_pt astrm=ip_gl.all_tcp_convs+i;
  167.         tcp_release_connection(astrm);
  168.      }
  169. }
  170.  
  171. /*
  172.  * handle action on each tcp connection
  173.  */
  174. void tcp_service_event(void)
  175. {
  176.      int i;
  177.      for(i=0;i<MAX_NUM_CONVS;i++) {
  178.          tcp_conv_pt astrm=ip_gl.all_tcp_convs+i;
  179.          if(astrm->state==ST_FREE)
  180.              tcp_init_stream(astrm);
  181.          if(astrm->state==ST_FREE)
  182.              continue;
  183.           if(astrm->terminating || (astrm->write_side.ipb.ioResult<0)) {
  184.              tcp_release_connection(astrm);
  185.              continue;
  186.          }
  187.         if(astrm->data_arrived)
  188.              tcp_recv_packet(astrm);
  189.          if(astrm->write_side.ipb.ioResult==1)
  190.              continue;
  191.          if(astrm->state==ST_LISTEN) {
  192.              get_finger_info(astrm->mactcp_send_buffer,
  193.                  astrm->mactcp_send_buffer+(sizeof(astrm->mactcp_send_buffer)-1000));
  194.              if(tcp_send_packet(astrm))
  195.                  continue;
  196.              astrm->state=ST_SEND;
  197.          }
  198.          if((astrm->write_side.ipb.ioResult!=1)&&(astrm->state==ST_SEND)) {
  199.               if(tcp_close(astrm))
  200.                   continue;
  201.               astrm->state=ST_CLOSE;
  202.           }
  203.           if((astrm->write_side.ipb.ioResult!=1)&&(astrm->state==ST_CLOSE))
  204.              tcp_release_connection(astrm);
  205.      }
  206. }
  207.  
  208. /*
  209.  * handle incomming data or connection drop
  210.  */
  211. static pascal void myTCPNotifyProc(StreamPtr tcpStream,
  212.     unsigned short eventCode,
  213.     Ptr userDataPtr,
  214.     unsigned short terminReason,
  215.     struct ICMPReport *icmpMsg)
  216. {
  217.     register tcp_conv_pt acnv=(tcp_conv_pt)userDataPtr;
  218.  
  219.     acnv->last_event=eventCode;
  220.     acnv->service_me=TRUE;
  221.  
  222.     switch (eventCode) {
  223.         case TCPTerminate:
  224.             acnv->terminating++;
  225.             break;
  226.         case TCPClosing:
  227.             acnv->closing++;
  228.             break;
  229.         case TCPULPTimeout:
  230.             break;
  231.         case TCPDataArrival:
  232.             acnv->data_arrived++;
  233.             break;
  234.         case TCPUrgent:
  235.             break;
  236.         case TCPICMPReceived:
  237.             break;
  238.         default:    
  239.             break;
  240.         }
  241.     tcp_wake(acnv->server_proc);
  242. }
  243.  
  244. /*
  245.  * release a tcp stream, aborting any io in progress
  246.  */
  247. void tcp_release_connection(tcp_conv_pt sconv)
  248. {
  249.     if(sconv->tcpStream!=0) {
  250.         int err;
  251.         TCPiopb ipb;        /* io parameters for current io */
  252.         memset(&ipb,0,sizeof(ipb));
  253.         ipb.csCode = TCPRelease;
  254.         ipb.ioCRefNum = ip_gl.refnum;
  255.         ipb.tcpStream = sconv->tcpStream;
  256.         ipb.csParam.globalInfo.userDataPtr= (char*)sconv; //use globalInfo, has same offset
  257.         err=PBControl((ParmBlkPtr)&ipb, FALSE);
  258.         if(err!=0)
  259.             DebugStr("\pError releasing a TCP stream");
  260.     }
  261.     memset(sconv,0,sizeof(*sconv));
  262. }
  263.  
  264. /*
  265.  * allocate io buffers
  266.  * return true on error
  267.  */
  268. int tcp_allocate_memory(void)
  269. {
  270.     if(ip_gl.all_tcp_convs!=0)
  271.         return FALSE;
  272.     ip_gl.all_tcp_convs=(tcp_conv_pt)NewPtrClear(sizeof(*ip_gl.all_tcp_convs)*MAX_NUM_CONVS);
  273.     if(ip_gl.all_tcp_convs==0)
  274.         return TRUE;
  275.     return FALSE;
  276. }
  277.  
  278. /*
  279.  * open the mactcp device driver
  280.  * returns true on an error
  281.  */
  282. int tcp_open_driver(void)
  283. {
  284.     int err;
  285.     TCPiopb pb;
  286.     if(ip_gl.refnum!=0)
  287.         return TRUE;
  288.     memset(&pb,0,sizeof(pb));
  289.  
  290.     pb.ioNamePtr = (char*)"\p.IPP";
  291.     err=PBOpen((ParmBlkPtr)&pb,FALSE);
  292.     if(err!=0)
  293.         return TRUE;
  294.     ip_gl.refnum = pb.ioCRefNum;
  295.     return FALSE;
  296. }
  297.  
  298. /*
  299.  * create a tcp stream
  300.  */
  301. int tcp_create_stream(tcp_conv_pt uptr)
  302. {
  303.     TCPiopb ipb;
  304.     uptr->server_proc= &ip_gl.server_proc;
  305.     memset(&ipb,0,sizeof(ipb));
  306.     ipb.csParam.create.rcvBuff = (Ptr)(uptr->mactcp_recv_buffer);
  307.     ipb.csParam.create.rcvBuffLen = MACTCP_RECV_BUFFER_LEN;
  308.     ipb.csParam.create.notifyProc = myTCPNotifyProc;
  309.     ipb.csParam.create.userDataPtr = (Ptr)uptr;
  310.  
  311.     ipb.csCode = TCPCreate;
  312.     if(tcp_do_tio(uptr,&ipb))
  313.         return TRUE;
  314.     uptr->tcpStream=ipb.tcpStream;
  315.     return FALSE;
  316. }
  317.  
  318. /*
  319.  * is any incomming data available on this connection
  320.  */
  321. static int tcp_is_data_available(tcp_conv_pt sconv)
  322. {
  323.     TCPiopb ipb;                /* io parameters for current io */
  324.     if(sconv->data_arrived==0)
  325.         return FALSE;
  326.     sconv->data_arrived=0;        /*we will notice it*/
  327.  
  328.     memset(&ipb,0,sizeof(ipb));
  329.     ipb.csCode = TCPStatus;
  330.     ipb.csParam.status.userDataPtr= (char*)sconv;
  331.     if(tcp_do_tio(sconv,&ipb))
  332.         return FALSE;
  333.  
  334.     if (ipb.csParam.status.amtUnreadData <= 0)    
  335.         return FALSE;
  336.  
  337.     sconv->data_arrived++;
  338.     return TRUE;
  339. }
  340.  
  341. /*
  342.  * close a tcp stream
  343.  */
  344. int tcp_close(tcp_conv_pt uptr)
  345. {
  346.     memset(&uptr->write_side.ipb,0,sizeof(uptr->write_side.ipb));
  347.     uptr->write_side.ipb.csCode = TCPClose;
  348.     
  349.        if(tcp_do_tio_async(uptr,&uptr->write_side))
  350.         return TRUE;
  351.     return FALSE;
  352. }
  353.  
  354. /*
  355.  * transfer outgoing packets into MacTCP output buffer
  356.  */
  357. int tcp_send_packet(tcp_conv_pt sconv)
  358. {
  359.     memset(&sconv->write_side.ipb,0,sizeof(sconv->write_side.ipb));
  360.     sconv->write_side.awds[1].length = 0;
  361.     sconv->write_side.awds[1].ptr="mumble";
  362.     sconv->write_side.awds[0].length = (short)strlen(sconv->mactcp_send_buffer);
  363.     sconv->write_side.awds[0].ptr=sconv->mactcp_send_buffer;
  364.  
  365.     sconv->write_side.ipb.csParam.send.wdsPtr  =(Ptr)&sconv->write_side.awds;
  366.     sconv->write_side.ipb.csParam.send.ulpTimeoutValue=SEND_TIMEOUT;
  367.     sconv->write_side.ipb.csParam.send.validityFlags=timeoutValue;
  368.     sconv->write_side.ipb.csParam.send.pushFlag=TRUE;
  369.     sconv->write_side.ipb.csParam.send.userDataPtr= (char*)sconv;
  370.     sconv->write_side.ipb.csCode = TCPSend;
  371.        if(tcp_do_tio_async(sconv,&sconv->write_side))
  372.         return TRUE;
  373.      return FALSE;
  374. }
  375.  
  376. #define NUM_RDS_ENTIRES (1)
  377.  
  378. /*
  379.  * recieve data on this connection
  380.  * the data is left in an internal mactcp buffer which must be returned to mactcp
  381.  * with the returnTCPbuffer proceedure
  382.  */
  383. int tcp_recv_packet(tcp_conv_pt sconv)
  384. {
  385.     TCPiopb     ipb;                /* io parameters for current io */
  386.     wdsEntry       awds[NUM_RDS_ENTIRES];
  387.  
  388.     if (sconv->data_arrived <= 0)
  389.         return FALSE;             /*no data*/
  390.  
  391.     memset(&awds,0,sizeof(awds));
  392.     memset(&ipb,0,sizeof(ipb));
  393.        ipb.csParam.receive.commandTimeoutValue=1;        //abort as soon as possible on an error
  394.     ipb.csParam.receive.rdsPtr=(Ptr)&awds;
  395.     ipb.csParam.receive.rdsLength = NUM_RDS_ENTIRES;
  396.     ipb.csParam.receive.userDataPtr= (char*)sconv;
  397.     ipb.csCode = TCPNoCopyRcv;
  398.     if(tcp_do_tio(sconv,&ipb))
  399.         return FALSE;
  400.     if(ipb.csParam.receive.rdsLength>0) {
  401.         if((ipb.csParam.receive.rdsLength>0) &&
  402.             (awds[0].length==3) &&
  403.             (memcmp(awds[0].ptr,"die",3)==0))
  404.                 sip_keep_running=FALSE;
  405.            ipb.csCode = TCPRcvBfrReturn;
  406.         if(tcp_do_tio(sconv,&ipb))
  407.             return FALSE;
  408.     }
  409.  
  410.     sconv->data_arrived--;
  411.     return TRUE;
  412. }
  413.